﻿using System;
using System.IO;
using System.Net.Sockets;
using System.Windows.Forms;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;

namespace CarController
{
    public partial class Display : Form
    {
        WebCam_Capture.WebCamCapture webCamCapture = new WebCam_Capture.WebCamCapture();
        TcpClient tdp;
        NetworkStream ns;
        Queue<byte[]> videoimages = new Queue<byte[]>();
        DateTime dt;
        long time;
        Random rand = new Random();
        public int imageheight = 480;
        public int imagewidth = 640;

        public Display(string h, int p)
        {
            webCamCapture.ImageCaptured += new WebCam_Capture.WebCamCapture.WebCamEventHandler(this.WebCamCapture_ImageCaptured);
            tdp = new TcpClient();
            String hostname = h;
            int port = p;
            tdp.Connect(hostname, port);
            Console.WriteLine("TDP connection to:" + hostname + ":" + port);
            InitializeComponent();
            runVideo();
        }

        public Display(TcpClient tcp)
        {

            webCamCapture.ImageCaptured += new WebCam_Capture.WebCamCapture.WebCamEventHandler(this.WebCamCapture_ImageCaptured);
            ns = tcp.GetStream();

            Console.WriteLine("TCP connection from: " + tcp.ToString());
            InitializeComponent();

            runVideo();
        }

        [STAThread]
        void runVideo()
        {
            webCamCapture.CaptureHeight = pictureBox1.Height = imageheight;
            webCamCapture.CaptureWidth = pictureBox1.Width = imagewidth;

            // change the capture timeframe
            webCamCapture.TimeToCapture_milliseconds = 40;
            webCamCapture.Start(0);
            
        }

        private bool ThumbnailCallback()
        {
            return false;
        }

        private void WebCamCapture_ImageCaptured(object source, WebCam_Capture.WebcamEventArgs e)
        {
            Image.GetThumbnailImageAbort dummyCallBack = new Image.GetThumbnailImageAbort(ThumbnailCallback);

            try
            {
                //store temporary image from webcam and resize
                Image x = e.WebCamImage;
                Image y = x.GetThumbnailImage(imagewidth, imageheight, dummyCallBack, IntPtr.Zero);

                //collect current car time and convert to 64-bit
                dt = DateTime.Now;
                time = dt.ToBinary();

                //convert time and resized image into byte array for transmission
                byte[] imagebytes = imageToByteArray(y);

                //buffer byte data and begin transmission
                videoimages.Enqueue(imagebytes);
                new Thread(sendData).Start();

                //memory clear up
                x.Dispose();
                y.Dispose();
            }
            catch
            {
            }
        }

        private void sendData()
        {
            try
            {
                byte[] imagebytes = videoimages.Dequeue();
                ns.Write(imagebytes, 0, imagebytes.Length);
                Console.WriteLine("Image Size:" + imagebytes.Length);
                ns.Flush();
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("There was no data to send...");
            }
            catch (SocketException soc)
            {
                Console.WriteLine(soc.StackTrace);
            }
            catch
            {
            }
        }

        public byte[] imageToByteArray(System.Drawing.Image imageIn)
        {
            //get most recent difference from ALIVE mechanism
            long diff = CarNetworkInterface.difference;

            //create timestamp for sending to user
            byte[] timebytes = longToBytes(time-diff);

            //convert image to bytes
            MemoryStream ms = new MemoryStream();
            imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] imagebytes = ms.ToArray();

            //append image data onto timestamp
            Array.Resize(ref timebytes, imagebytes.Length + 8);
            Array.Copy(imagebytes,0, timebytes, 8, imagebytes.Length);
            return timebytes;
        }

        private byte[] longToBytes(long l)
        {
            return BitConverter.GetBytes(l);
        }

        private void Display_FormClosed(object sender, FormClosedEventArgs e)
        {
            webCamCapture.Stop();
            webCamCapture.Dispose();
        }

    }
}
